package com.itheima.springbootwebtlias.service.Impl;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.itheima.springbootwebtlias.anno.LogOperation;
import com.itheima.springbootwebtlias.anno.MyLog;
import com.itheima.springbootwebtlias.exception.PasswordErrorException;
import com.itheima.springbootwebtlias.exception.UsernameNotExistException;
import com.itheima.springbootwebtlias.mapper.EmpExprMapper;
import com.itheima.springbootwebtlias.mapper.EmpMapper;
import com.itheima.springbootwebtlias.pojo.*;
import com.itheima.springbootwebtlias.service.EmpLogService;
import com.itheima.springbootwebtlias.service.EmpService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

@Slf4j
@Service

public class EmpServiceImpl implements EmpService {
    @Autowired
    private EmpMapper empMapper;

    @Autowired
    private EmpExprMapper empExprMapper;

    @Autowired
    private EmpLogService empLogService;

    //分页 + 条件 查询
    @Override
    public PageResult page(EmpQueryParam queryparam) {

        //1.查询指定的数据：select * from emp where 条件 limit ?.?
//        int start = (queryparam.getPage()-1)*queryparam.getPageSize();
//        queryparam.setPage(start);
//        List<Emp> emps = empMapper.selectPage(queryparam);
        //2.查询总记录数：select count(*) from emp where 条件

        //3.封装PageResult对象，返回

        //--------------------------

        //1.使用分页插件实现分页查询
        //1.1启动分页插件
        PageHelper.startPage(queryparam.getPage(),queryparam.getPageSize());

        //1.2调用分页插件增强的持久层方法
         Page<Emp> page = (Page<Emp>)empMapper.selectByCondition(queryparam);

         //1.3 从分页插件增强方法的返回结果中，获取数据封装到PageResult对象中
         PageResult pageResult = new PageResult(page.getTotal(),page.getResult());

         return pageResult;
    }

    //新增员工
    @Override
    @Transactional //保持数据的完整性一致性
    @LogOperation
    public void add(Emp emp) {
        //1.调用持久层Mapper，向员工表中添加员工信息
        //补充基础数据
        try{
        emp.setCreateTime(LocalDateTime.now());
        emp.setUpdateTime(LocalDateTime.now());
        empMapper.insert(emp); //mybatis框架，设置主键返回

//      int i = 10 / 0;

//            if (true){
//            throw new RuntimeException("手动抛出异常");
//        }
        //2.如果有工作经历信息
        List <EmpExpr> exprList = emp.getExprList();
        if(exprList!=null && exprList.size()>0){
            //设置当前员工经理所属的员工信息
            exprList.stream().forEach(empExpr ->
                empExpr.setEmpId(emp.getId()));

            //调用持久层Mapper，向员工工作经历表中添加员工工作经历信息
            //方式一：
            /*for (EmpExpr empExpr : exprList) {
                empExprMapper.insert(empExpr);
            }*/

            //方式二：批量操作,交互少，性能高
            empExprMapper.insertBatch(exprList); //insert values (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,)
        }
    } finally {
            //3.记录日志操作
            EmpLog empLog = new EmpLog(emp.getId(),LocalDateTime.now(),"添加员工"+emp.getName());
            empLogService.insertLog(empLog);
        }
        }

        //查询所有员工
    @Override
    public List<Emp> selectAll() {
       List <Emp> emps = empMapper.selectAll();

       //返回查询列表
        return emps;
    }

    //批量删除员工
    @Transactional //保持数据的完整性一致性
    @Override
    @MyLog
    @LogOperation
    public void removeBatch(List<Integer> ids) {
        //1.调用持久层Mapper，批量删除员工信息
        //delete from emp where id in (?,?,?,?)
        empMapper.deleteBatchById(ids);

        //2.调用持久层EmpExprMapper，批量删除员工工作经历信息
        empExprMapper.deleteBatchByEmpIds(ids);
    }

    //根据id查询员工信息
    @Override
    public Emp queryById(Integer id) {

        //方案一：两次单表查询
        //1.调用持久层Mapper，根据id查询员工信息
//        Emp emp = empMapper.selectById(id); //单表
//
//        //2.调用持久层EmpExprMapper，根据员工id查询员工工作经历信息
//        List<EmpExpr> exprList = empExprMapper.selectByEmpId(id); //单表
//
//        //3.将员工信息和员工工作经历信息封装到Emp对象中
//        emp.setExprList(exprList);

        //方案二：一次多表查询（数据量大，性能低）
        Emp emp = empMapper.selectByIdAndExprs(id);
        return emp;
    }

    //更新员工信息
    @Transactional
    @Override
    @LogOperation
    public void update(Emp emp) {
        //1.调用持久层Mapper，更新员工信息
        emp.setUpdateTime(LocalDateTime.now()); //同步更新时间
        empMapper.update(emp);

        //2.调用持久层EmpExprMapper，更新员工工作经历信息
        //2.1删除员工对应的工作经历信息
        List<Integer> ids = new ArrayList<>();
        ids.add(emp.getId());
        empExprMapper.deleteBatchByEmpIds(ids);
        //2.2批量添加员工对应的所有工作经历信息
        if (emp.getExprList()!=null && emp.getExprList().size()>0){
            //设置新增的所属员工信息
            emp.getExprList().stream().forEach(empExpr ->
                    empExpr.setEmpId(emp.getId()));

        empExprMapper.insertBatch(emp.getExprList());
        }
    }

    @Override
    public Emp checkLogin(Emp emp) {
      //1.调用持久层EmpMapper，查询员工信息
        Emp resultEmp = empMapper.selectByUsername(emp.getUsername());

        //2.判断员工是否存在，如果不存在，客户不存在（登陆失败）
        if (resultEmp==null){
            //业务异常，走异常处理机制，让全局异常处理器，封装登陆失败结果
            throw new UsernameNotExistException("用户名不存在");
        }

        //3.如果存在，比较密码，如果不存在，密码错误（登陆失败）
        if(!Objects.equals(resultEmp.getPassword(),emp.getPassword())){
            throw new PasswordErrorException("密码错误");
        }

        //4.登陆成功，返回员工信息
        return resultEmp;
    }

    /*
    spring框架提供，声明式事务，只需要添加注解即可进行事务控制管理
    //底层：动态代理
    //1.程序启动，spring框架扫描所有类中的所有方法
    //2.判断方法上是否添加了@Transactional注解
    //3.使用动态代理模式，创建当前类的代理对象，并将代理对象返回给spring容器管理，替换原来对象
    empServiceImplProxy.add(){
          try{
             //开启事务
             me

          }
    }
     */
}
